"""
SOP Repository Interface
========================

This module defines the repository interface for SOP (Standard Operating Procedure)
data access operations following the Repository pattern.
"""

from abc import ABC, abstractmethod
from typing import List, Optional
from .sop import SOP


class SOPRepository(ABC):
    """
    Abstract repository interface for SOP data access operations.
    
    This interface defines the contract for SOP data access,
    following the Repository pattern from Domain-Driven Design.
    """
    
    @abstractmethod
    def save(self, sop: SOP) -> SOP:
        """
        Save a SOP entity to the repository.
        
        Args:
            sop: The SOP entity to save
            
        Returns:
            The saved SOP entity with generated ID (if new)
            
        Raises:
            Exception: If there's an error saving the SOP
        """
        pass
    
    @abstractmethod
    def find_by_id(self, sop_id: int) -> Optional[SOP]:
        """
        Find a SOP by its ID.
        
        Args:
            sop_id: The ID of the SOP to find
            
        Returns:
            The SOP entity if found, None otherwise
        """
        pass
    
    @abstractmethod
    def find_all(self) -> List[SOP]:
        """
        Find all SOPs in the repository.
        
        Returns:
            List of all SOP entities
        """
        pass
    
    @abstractmethod
    def update(self, sop: SOP) -> SOP:
        """
        Update an existing SOP in the repository.
        
        Args:
            sop: The SOP entity to update
            
        Returns:
            The updated SOP entity
            
        Raises:
            Exception: If the SOP doesn't exist or there's an error updating
        """
        pass
    
    @abstractmethod
    def delete(self, sop_id: int) -> bool:
        """
        Delete a SOP from the repository.
        
        Args:
            sop_id: The ID of the SOP to delete
            
        Returns:
            True if the SOP was deleted, False if it didn't exist
            
        Raises:
            Exception: If there's an error deleting the SOP
        """
        pass
    
    @abstractmethod
    def find_by_subject(self, subject: str) -> List[SOP]:
        """
        Find SOPs by subject (partial match).
        
        Args:
            subject: The subject to search for
            
        Returns:
            List of SOP entities matching the subject
        """
        pass
    
    @abstractmethod
    def find_by_creator(self, created_by: str) -> List[SOP]:
        """
        Find SOPs by creator.
        
        Args:
            created_by: The creator to search for
            
        Returns:
            List of SOP entities created by the specified creator
        """
        pass
    
    @abstractmethod
    def find_by_ids(self, sop_ids: List[int]) -> List[SOP]:
        """
        Find SOPs by their IDs.
        
        Args:
            sop_ids: List of SOP IDs to find
            
        Returns:
            List of SOP entities matching the given IDs
        """
        pass